﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using CPN.PJN.Silverlight.Common.Configuration;


namespace CPN.PJN.Silverlight.Common.Logging.Configuration
{
    /// <summary>
    /// Cette classe permet de configurer le Logger
    /// </summary>
    public sealed class LoggerConfigurationManager
    {
        #region Private Members

        /// <summary>
        /// Instance du Gestionnaire de configuration du logger
        /// </summary>
        private static volatile LoggerConfigurationManager instance;

        /// <summary>
        /// Objet de synchronisation
        /// </summary>
        private static object syncRoot = new Object();

        #endregion

        #region Instance Property

        /// <summary>
        /// Propriété Instance du Gestionnaire de configuration du logger
        /// </summary>
        public static LoggerConfigurationManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new LoggerConfigurationManager();
                    }
                }

                return instance;
            }
        }

        #endregion

        #region LogCategoryDictionary Property

        /// <summary>
        /// Dictionnaire de categories
        /// </summary>
        public Dictionary<string, LogCategory> LogCategoryDictionary { get; private set; }

        #endregion

        #region Private Constructor

        /// <summary>
        /// Constructeur privé
        /// </summary>
        private LoggerConfigurationManager()
        {
            this.LogCategoryDictionary = new Dictionary<string, LogCategory>();
        }

        #endregion

        #region Configure Method

        /// <summary>
        /// Cette méthode permet de configurer la gestion des logs
        /// </summary>
        public void Configure()
        {
            this.ParseConfiguration(ConfigurationManager.Instance.ContentConfiguration);
        }

        #endregion

        #region ParseConfiguration Method

        /// <summary>
        /// Cette méthode permet de traiter les données
        /// </summary>
        /// <param name="data">donnée du fichier de configuration</param>
        private void ParseConfiguration(XElement dataElement)
        {
            try
            {
                if (dataElement.Elements("LoggingConfiguration") != null)
                {
                    this.LogCategoryDictionary.Clear();

                    foreach (XElement category in dataElement.Elements("LoggingConfiguration").Descendants("LogCategory"))
                    {
                        var logCategory = new LogCategory();
                        if (category.Attribute("name") != null)
                        {
                            logCategory.Name = category.Attribute("name").Value;
                            logCategory.IsEnabled = string.IsNullOrEmpty(category.Attribute("isEnabled").Value) || Convert.ToBoolean(category.Attribute("isEnabled").Value) ? true : false;

                            // Recherche de la severity minimale
                            bool severityConfigured = false;
                            if (!string.IsNullOrEmpty(category.Attribute("minLevel").Value))
                            {
                                var severity = new LogSeverity();
                                foreach (var field in typeof(LogSeverity).GetFields())
                                {
                                    if (field.Name.Equals(category.Attribute("minLevel").Value, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        logCategory.MinLevel = Convert.ToInt32(field.GetValue(severity));
                                        severityConfigured = true;
                                        break;
                                    }
                                }
                            }
                            if (!severityConfigured)
                            {
                                logCategory.MinLevel = LogSeverity.Verbose;
                            }
                            
                            // Ajout des Listeners
                            foreach (XElement listener in category.Descendants("LogListener"))
                            {
                                if (listener.Attribute("type") != null)
                                {
                                    var nameType = listener.Attribute("type").Value;
                                    var type = Type.GetType(nameType);
                                    if (type != null)
                                    {
                                        var implLogListner = Activator.CreateInstance(type) as LogListener;
                                        if (implLogListner != null)
                                        {
                                            if (listener.Attribute("name") != null)
                                            {
                                                implLogListner.Name = listener.Attribute("name").Value;
                                                implLogListner.Configure(listener);
                                                logCategory.LogListenerCollection.Add(implLogListner);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // Ajout de la catégorie de log
                        this.LogCategoryDictionary.Add(logCategory.Name, logCategory);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion

    }
}
